﻿using System;
using System.Collections.Generic;
using Sharp3D.Math.Core;

namespace GLWrap.MathExt
{
    public static class MathHelper
    {
        public static float DegreesToRadians(this float degrees)
        {
            return (float) (degrees/180.0*Math.PI);
        }

        public static float RadiansToDegrees(this float radians)
        {
            return (float) (radians*180.0/Math.PI);
        }

        public static float[] GetArray(this Vector4F vector)
        {
            return new[] {vector.X,vector.Y,vector.Z,vector.W};
        }

        public static float[] GetArray(this Vector3F vector)
        {
            return new[] {vector.X, vector.Y, vector.Z};
        }

        public static bool EqualWithEpsilan(this float v,float v2,float epsilan)
        {
            return (v >= (v2 - epsilan)) && (v <= (v2 + epsilan));
        }

        public static float NormalizeAngle(this float angle)
        {
            float a = angle;
           
            while (a <= 0.0) a += 360.0f;
            while (a >= 360.0) a -= 360.0f;

            return a;
        }

        public static Vector3F GetVector3F(this Vector4F v)
        {
            return new Vector3F(v.X,v.Y,v.Z);
        }
 
        public static float GetDegreesBetweenVectors(Vector3F v1, Vector3F v2)
        {
            if (v1 == v2) return 0;
            return RadiansToDegrees((float) Math.Acos(Vector3F.DotProduct(v1,v2)/v1.GetLength()/v2.GetLength()));
        }

        public static Quarter GetQuarter(Vector2F p1, Vector2F p2)
        {
            var quarters = new Dictionary<bool, IDictionary<bool, Quarter>>();
            quarters[false] = new Dictionary<bool, Quarter>();
            quarters[true] = new Dictionary<bool, Quarter>();
            
            quarters[false][false] = Quarter.Third;
            quarters[false][true] = Quarter.Second;
            quarters[true][false] = Quarter.Fourth;
            quarters[true][true] = Quarter.First;

            return quarters[p2.X > p1.X][p2.Y > p1.Y];
        }
    
        public static void MoveAngleToQuarter(ref float angle,Quarter quarter)
        {
            switch(quarter)
            {
                case Quarter.First:
                    break;
                case Quarter.Second:
                    angle = (float) (180.0 - angle);
                    break;
                case Quarter.Third:
                    angle = (float) (180.0 + angle);
                    break;
                case Quarter.Fourth:
                    angle *= -1;
                    break;
                default:
                    throw new ArgumentOutOfRangeException("quarter");
            }
        }
    }
}